#include <iostream>
#include "Socket.hpp"
#include "Protocol.hpp"

using namespace Protocol;

static void usage(const std::string &process)
{
    std::cout << std::endl
              << "Usage: " << process << " serverIp serverPort" << std::endl
              << std::endl;
}

// ./client serverIp serverPort
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(1);
    }

    std::string serverIp = argv[1];
    uint16_t serverPort = atoi(argv[2]);

    Sock sock;
    int socketFd = sock.Socket();
    if (!sock.Connect(socketFd, serverIp, serverPort))
    {
        std::cerr << "Connect error" << std::endl;
        exit(2);
    }

    bool quit = false;
    std::string buffer;
    // 客户端和服务端默认遵守协议：输入的就是"1 + 1"
    while (!quit)
    {
        // 1. 获取需求
        Request req;
        std::cout << "Please Enter # ";
        std::cin >> req._left >> req._op >> req._right;

        // 2. 序列化
        std::string str = req.Serialize();

        // 3. 添加长度报头
        str = Encode(str);

        // 4. 发送给服务端
        Send(socketFd, str);

        // 5. 读取结果
        while (true)
        {
            bool recvOk = Recv(socketFd, &buffer);
            if (!recvOk)
            {
                quit = true;
                break;
            }

            std::string package = Decode(buffer);
            if (package.empty())
                continue;

            Response resp;
            resp.Deserialize(package);
            std::string err;
            switch (resp._code)
            {
            case DIVZERO:
                err = "除0错误";
                break;
            case MODZERO:
                err = "模0错误";
                break;
            case ILLEGAL:
                err = "非法操作";
                break;
            default:
                // 该输出只在JSON协议下有用 因为自定义协议的response没有对输出信息做反序列化
                std::cout << resp._left << resp._op << resp._right << " = " << resp._result << " [success]" << std::endl;
                break;
            }
            if (!err.empty())
                std::cerr << err << std::endl;

            break;
        }
    }
    close(socketFd);
    return 0;
}

